﻿/*
 * 由SharpDevelop创建。
 * 用户： 11131
 * 日期: 2024/12/29
 * 时间: 15:38
 * 
 * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
 */
using System;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.IO;

using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
using System.IO.Ports;

namespace Simplified_ESP_download_tool
{
	/// <summary>
	/// Description of MainForm.
	/// </summary>
	public partial class MainForm : Form
	{
		public SerialPort serialPort = new SerialPort();
		public String shell = "";
		private String filePath = "";
		
		public MainForm()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
			
			//
			// TODO: Add constructor code after the InitializeComponent() call.
			//
			getComlist();
			
			cbDLSpeed.SelectedIndex = 5;
			
			IniFile("./config.ini");
			string path =  ReadValue("config", "download_path", "");
			string speed =  ReadValue("config", "download_speed", "5");
			
			tbfirmwareFilePath.Text = path;
			cbDLSpeed.SelectedIndex = int.Parse(speed);
			
//			ToolTip toolTip1 = new ToolTip();

//			// 设置显示时间
//			toolTip1.AutoPopDelay = 5000;
//			toolTip1.InitialDelay = 1000;
//			toolTip1.ReshowDelay = 500;
//			toolTip1.ShowAlways = true;
//			
//			// 设置控件的ToolTipText属性
//			comopenbt.SetToolTip(toolTip1, "下载按钮，点击开始下载");
//			button2.SetToolTip(toolTip1, "擦除按钮，点击擦除整个flash");
		}
		
		// 导入Windows API函数
		[DllImport("kernel32")]
		private static extern long WritePrivateProfileString(string section, string key, string value, string filePath);
		
		[DllImport("kernel32")]
		private static extern int GetPrivateProfileString(string section, string key, string defaultValue, StringBuilder returnValue, int size, string filePath);
		
		public void IniFile(string filePath)
		{
		  this.filePath = filePath;
		}
		
		public string ReadValue(string section, string key, string defaultValue = "")
		{
		  StringBuilder returnValue = new StringBuilder(255);
		  GetPrivateProfileString(section, key, defaultValue, returnValue, 255, filePath);
		  return returnValue.ToString();
		}
		
		public void WriteValue(string section, string key, string value)
		{
		  WritePrivateProfileString(section, key, value, filePath);
		}
		
		void getComlist()
		{
			comlistcb.ResetText();
			string[] ports = SerialPort.GetPortNames();
			comlistcb.DataSource = ports;
		}
		
		void ComscanbtClick(object sender, EventArgs e)
		{
			getComlist();
		}
		
		void ComopenbtClick(object sender, EventArgs e)
		{
			if(comlistcb.SelectedItem == null) 
			{
				logView.AppendText("请选择串口\n");
				return;
			}
			
			if(cbDLSpeed.SelectedItem == null) 
			{
				logView.AppendText("请选择波特率\n");
				return;
			}
			
			if(tbfirmwareFilePath.Text == "") 
			{
				logView.AppendText("请选择需要下载的文件\n");
				return;
			}
			
			const string filePath = @"./tools/esptool.exe"; // 替换为你想要检查的文件路径
	        if (!File.Exists(filePath))
	        {
	            updateLog("esptools.exe 文件不存在");
	            return;
	        }
        
            comopenbt.Text = "下载中";
            comopenbt.BackColor = Color.Blue;
            comopenbt.ForeColor = Color.White;
          	
			progressBar1.Value = 0;
		    tbpBar.Text = "0%";
		     
            string firmwareFilePath = tbfirmwareFilePath.Text; // 固件文件的路径
	        string com = comlistcb.SelectedItem.ToString(); // 串口名称，根据实际情况修改
	        string dlspeed = cbDLSpeed.SelectedItem.ToString();
	        // esptool命令
	        string command = " -p " + com + " -b " + dlspeed + " write_flash 0x00000 " + firmwareFilePath;
	        
			sendCmd(command);
		}
		
		
		public void sendCmdThread() {
			if (shell.Length > 0) {
				Process p = new Process();
				p.StartInfo.FileName = "./tools/esptool.exe";
				p.StartInfo.Arguments = shell;
				p.StartInfo.RedirectStandardInput = true;
				p.StartInfo.RedirectStandardOutput = true;
				p.StartInfo.RedirectStandardError = true;
				p.StartInfo.CreateNoWindow = true;//true表示不显示黑框，false表示显示dos界面 
				p.StartInfo.UseShellExecute = false;
				
				p.EnableRaisingEvents = true;//在进程终止时是否应引发 Process.Exited 事件
				
				string ressult = "";
				
				p.OutputDataReceived += (s, ev) => { 
					updateLog(ev.Data);
					if(ev.Data != null) {
					   if(ev.Data.StartsWith("Writing")) {
							Match match = Regex.Match(ev.Data, @"\((\d+) %\)");
							if (match.Success)
							{
							    // 将匹配到的字符串转换为整数
							    int percentage = int.Parse(match.Groups[1].Value);
							    updateProgressBar(percentage);
							}
						} else if(ev.Data.IndexOf("Hash of data verified.") != -1) {
							updateResult("下载完成", Color.Green);
							ressult = "下载完成";
						} else if(ev.Data.IndexOf("Failed to connect to Espressif device") != -1) {
							updateResult("连接失败", Color.Red);
							ressult =  "连接失败";
						} else if(ev.Data.IndexOf("Chip erase completed successfully") != -1) {
							updateResult("擦除完成", Color.Green);
							ressult = ("擦除完成");
							updateProgressBar(100);
						}
					}
					
				};
				
				p.ErrorDataReceived += (s, ev) => { 
					updateLog(ev.Data);
				};
				
				p.Exited += (s, ev) => { 
					updateLog(ev.ToString());
					updateLog(ressult);
				};
				
				p.Start();
				
				p.StandardInput.WriteLine("");
				p.StandardInput.WriteLine("");
				
				//开始异步读取输出
				p.BeginOutputReadLine();
				p.BeginErrorReadLine();
				
				//调用WaitForExit会等待Exited事件完成后再继续往下执行。
				p.WaitForExit();
				p.Close();
				
				updateLog("exit");   
				shell = "";
			}
		}
	
		public void sendCmd(string cmd) {
			shell = cmd;
			new Thread(new ThreadStart(sendCmdThread)).Start();
		}
		
		private delegate void UpdateLog();
		private delegate void UpdateProgressBar();
		private delegate void UpdateResult();
		
		private void updateLog(String log) {
		 UpdateLog set = delegate()
		 {
		     // disable once ConvertToLambdaExpression
		     logView.AppendText("\n" + log);
		     logView.ScrollToCaret();
		 };
		 this.Invoke(set);
		}
		
		private void updateProgressBar(int val) {
		 UpdateProgressBar set = delegate()
		 {
		     // disable once ConvertToLambdaExpression
		     progressBar1.Value = val;
		     tbpBar.Text = val + "%";
		 };
		 this.Invoke(set);
		}
		
		private void updateResult(String text, Color color) {
		 UpdateResult set = delegate()
		 {
		    // disable once ConvertToLambdaExpression
	     	comopenbt.Text = text;
            comopenbt.BackColor = color;
            comopenbt.ForeColor = Color.White;
		     
		 };
		 this.Invoke(set);
		}
		
		void Button1Click(object sender, EventArgs e)
		{
			string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
			string file = "";
			string path = "";
			
			if(tbfirmwareFilePath.Text != null)
			{
				path = tbfirmwareFilePath.Text;
			}
			else {
			
				path = desktopPath;
			}
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Multiselect = true;      				//该值确定是否可以选择多个文件
            dialog.Title = "Select firmware file";     					//弹窗的标题
            dialog.InitialDirectory = path;       		//默认打开的文件夹的位置
            dialog.Filter = "Firmware file(*.bin)|*.bin|All file(*.*)|*.*";       //筛选文件
//            dialog.ShowHelp = true;     //是否显示“帮助”按钮
            
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                file = dialog.FileName;
                tbfirmwareFilePath.Text = file;
                WriteValue("config", "download_path", file);
            }
		}
		void CbDLSpeedSelectedIndexChanged(object sender, EventArgs e)
		{
			WriteValue("config", "download_speed", cbDLSpeed.SelectedIndex.ToString());
		}
		void Button2Click(object sender, EventArgs e)
		{
			if(comlistcb.SelectedItem == null) 
			{
				logView.AppendText("请选择串口\n");
				return;
			}
			
			if(cbDLSpeed.SelectedItem == null) 
			{
				logView.AppendText("请选择波特率\n");
				return;
			}
			
			const string filePath = @"./tools/esptool.exe";
	        if (!File.Exists(filePath))
	        {
	            updateLog("esptools.exe 文件不存在");
	            return;
	        }
        
			progressBar1.Value = 0;
		    tbpBar.Text = "0%";
		    
		    comopenbt.Text = "擦除中";
            comopenbt.BackColor = Color.Blue;
            comopenbt.ForeColor = Color.White;
            
		    string com = comlistcb.SelectedItem.ToString(); // 串口名称，根据实际情况修改
	        string dlspeed = cbDLSpeed.SelectedItem.ToString();
	        // esptool命令
	        string command = " -p " + com + " -b " + dlspeed + " erase_flash";
			sendCmd(command);
		}
	}
	
}
